/**
 * This file is part of routerdns.
 * 
 * AUTHORS
 *     Oliver Mader  <dotb52@gmail.com>
 * 
 * Copyright (C) 2009  Oliver Mader
 * 
 * Routerdns is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Routerdns is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with routerdns.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "ssl.h"

#include <openssl/crypto.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>

#include "log.h"

static SSL *ssl = NULL;
static SSL_CTX *ctx = NULL;

static void ssl_error();

/* init and connect ssl */
extern int ssl_init(int sock)
{
	/* init the openssl library */
	SSL_load_error_strings();
	SSL_library_init();
	
	ctx = SSL_CTX_new(SSLv23_client_method());
	
	if (ctx == NULL) {
		ssl_error();
		ssl_free();
		return SSL_ERROR;
	}
	
	ssl = SSL_new(ctx);
	
	if (ssl == NULL) {
		ssl_error();
		ssl_free();
		return SSL_ERROR;
	}
	
	if (SSL_set_fd(ssl, sock) == 0) {
		ssl_error();
		ssl_free();
		return SSL_ERROR;
	}
	
	RAND_poll();
	
	while (RAND_status() == 0) {
		unsigned short rand_ret = rand() % 65536;
		RAND_seed(&rand_ret, sizeof(rand_ret));
	}
	
	if (SSL_connect(ssl) != 1) {
		ssl_error();
		ssl_free();
		return SSL_ERROR;
	}
	
	return SSL_OK;
}

/* free ssl stuff */
extern void ssl_free()
{
	if (ssl != NULL) {
		SSL_shutdown(ssl);
		SSL_free(ssl);
		
		ssl = NULL;
	}

	if (ctx != NULL) {
		SSL_CTX_free(ctx);
	
		ctx = NULL;
	}
	
	ERR_free_strings();
}

/* log all ssl errors in the queue */
static void ssl_error()
{
	while (1) {
		unsigned long err = ERR_get_error();
		
		if (err == 0)
			break;
	
		log_error("A SSL related error occured: %s", ERR_reason_error_string(
			err));
	}
}
